#pragma once
class Symbol;

namespace IcyCrystal {
	enum PrimitiveType {
		PRIM_TYPE_INT, PRIM_TYPE_FLOAT,
		PRIM_TYPE_CHAR, PRIM_TYPE_STRING,
		PRIM_TYPE_POINTER,
		PRIM_TYPE_ARRAY,
		PRIM_TYPE_VLA,
		PRIM_TYPE_FUNCTION,
		PRIM_TEMP
	};
	enum ArrayNumElements {
		ARRAY_ELEM_CONST, ARRAY_ELEM_DYN,
		ARRAY_ELEM_WAIT
	};
	class SyntaxTree;
	
	class Type {
	public:
		Type(){
			extra.pointTo = NULL;
			
		}
		PrimitiveType primitiveType;
		unsigned int size;

		// The number of elements in an array.
		union {
			SyntaxTree* runtimeExpr;
			int constNumElems;
		} arrayAccess;
		ArrayNumElements arraySize;

		
		union {
			/* Used by pointers: The type that this pointer points to */
			Type* pointTo;
		} extra;

		string primitiveTypeToString(){
			string p;
			switch(primitiveType){
			case PRIM_TYPE_INT:
				return "int";
			case PRIM_TYPE_FLOAT:
				return "float";
			case PRIM_TYPE_CHAR:
				return "char";
			case PRIM_TYPE_POINTER:
				// Build it!
				p = extra.pointTo->primitiveTypeToString();
				p += "*";
				return p;
			case PRIM_TYPE_ARRAY:
				p = extra.pointTo->primitiveTypeToString();
				p += "[]";
				return p;
			case PRIM_TYPE_STRING:
				return "string";
			default:
				throw ParserException("primitiveTypeToString(): Unexpected primitivetype");
			}
		}
	};


}
